package com.zc.topmod.impl;

import com.zc.topmod.utils.CalculationEquations;
import com.zc.topmod.utils.FileUtils;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by zhucan on 19/2/3.
 */
@Slf4j
public class FlatMeasCalFormulaImpl {
    static DecimalFormat df = new DecimalFormat("0.###############");
    static double doublezero=0.000000001;
    /**
     * 计算B点
     *
     * @param aerfa
     * @param belta
     * @param d2
     * @return
     */
    public static double[] calPointB(double aerfa, double belta, double d2) {
        double[] point = new double[3];
        double fenmu = Math.sqrt(Math.pow(Math.sin(aerfa) * Math.cos(belta), 2) + Math.pow(Math.cos(aerfa) * Math.sin(belta), 2) + Math.pow(Math.cos(aerfa) * Math.cos(belta), 2));

        int n = 3;
        // 系数矩阵
        double[][] test = {{Math.sin(aerfa) * Math.cos(belta) / fenmu, Math.cos(aerfa) * Math.sin(belta) / fenmu, (-1) * Math.cos(aerfa) * Math.cos(belta) / fenmu},
                {Math.cos(aerfa), 0, Math.sin(aerfa)},
                {0, Math.cos(belta), Math.sin(belta)}};
        // 方程的解
        double[] value = {d2, 0, 0};
        double[] result = null;
        try {
            // 转换成增广矩阵并进行初等行变化
            double[][] mathMatrix = CalculationEquations.mathDeterminantCalculation(CalculationEquations.transferMatrix(
                    test, value));
            // 找出非零行的个数
            int checkMatrixRow = CalculationEquations.effectiveMatrix(mathMatrix);
            // 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况
            if (n > checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,少于未知数个数，所以该方程有无数组解");
            } else if (n < checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,多于未知数个数，所以该方程有无解");
            } else {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,等于未知数个数，所以该方程有解");
                result = CalculationEquations.calculationResult(mathMatrix);
                for (int i = 0; i < result.length; i++) {
                    System.out.println("方程组的解为x" + (i + 1) + "="
                            + df.format(result[i]));
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (result[0] > 0 && result[1] > 0 && result[2] < 0) {
            point[0] = result[0];
            point[1] = result[1];
            point[2] = result[2];
            return point;
        }

        // 负数解
        // 系数矩阵
        test = new double[][]{{(-1) * Math.sin(aerfa) * Math.cos(belta) / fenmu, (-1) * Math.cos(aerfa) * Math.sin(belta) / fenmu, Math.cos(aerfa) * Math.cos(belta) / fenmu},
                {Math.cos(aerfa), 0, Math.sin(aerfa)},
                {0, Math.cos(belta), Math.sin(belta)}};
        // 方程的解
        value = new double[]{d2, 0, 0};
        result = null;
        try {
            // 转换成增广矩阵并进行初等行变化
            double[][] mathMatrix = CalculationEquations.mathDeterminantCalculation(CalculationEquations.transferMatrix(
                    test, value));
            // 找出非零行的个数
            int checkMatrixRow = CalculationEquations.effectiveMatrix(mathMatrix);
            // 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况
            if (n > checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,少于未知数个数，所以该方程有无数组解");
            } else if (n < checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,多于未知数个数，所以该方程有无解");
            } else {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,等于未知数个数，所以该方程有解");
                result = CalculationEquations.calculationResult(mathMatrix);
                for (int i = 0; i < result.length; i++) {
                    System.out.println("方程组的解为x" + (i + 1) + "="
                            + df.format(result[i]));
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (result[0] > 0 && result[1] > 0 && result[2] < 0) {
            point[0] = result[0];
            point[1] = result[1];
            point[2] = result[2];
            return point;
        }

        return point;
    }

    /**
     * 计算点A
     *
     * @param aerfa
     * @param belta
     * @param d1
     * @param l1
     * @param x2
     * @param y2
     * @param z2
     * @return
     */
    public static double[] calPointA(double aerfa, double belta, double d1, double l1, double x2, double y2, double z2) {
        double[] point = new double[3];
        double fenmu = Math.sqrt(Math.pow(Math.sin(aerfa) * Math.cos(belta), 2) + Math.pow(Math.cos(aerfa) * Math.sin(belta), 2) + Math.pow(Math.cos(aerfa) * Math.cos(belta), 2));

        int n = 3;
        // 系数矩阵
        double[][] test = {{Math.sin(aerfa) * Math.cos(belta) / fenmu, Math.cos(aerfa) * Math.sin(belta) / fenmu, (-1) * Math.cos(aerfa) * Math.cos(belta) / fenmu},
                {Math.cos(aerfa), 0, Math.sin(aerfa)},
                {0, (-1) * z2, y2}};
        // 方程的解
        double[] value = {d1, l1, y2 * l1 * Math.sin(aerfa)};
        double[] result = null;
        try {
            // 转换成增广矩阵并进行初等行变化
            double[][] mathMatrix = CalculationEquations.mathDeterminantCalculation(CalculationEquations.transferMatrix(
                    test, value));
            // 找出非零行的个数
            int checkMatrixRow = CalculationEquations.effectiveMatrix(mathMatrix);
            // 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况
            if (n > checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,少于未知数个数，所以该方程有无数组解");
            } else if (n < checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,多于未知数个数，所以该方程有无解");
            } else {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,等于未知数个数，所以该方程有解");
                result = CalculationEquations.calculationResult(mathMatrix);
                for (int i = 0; i < result.length; i++) {
                    System.out.println("方程组的解为x" + (i + 1) + "="
                            + df.format(result[i]));
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (result[0] > 0 && result[1] > 0 && result[2] < 0) {
            point[0] = result[0];
            point[1] = result[1];
            point[2] = result[2];
            return point;
        }

        // 负数解
        // 系数矩阵
        test = new double[][]{{Math.sin(aerfa) * Math.cos(belta) / fenmu, Math.cos(aerfa) * Math.sin(belta) / fenmu, (-1) * Math.cos(aerfa) * Math.cos(belta) / fenmu},
                {Math.cos(aerfa), 0, Math.sin(aerfa)},
                {0, (-1) * z2, y2}};
        // 方程的解
        value = new double[]{d1, l1, y2 * l1 * Math.sin(aerfa)};
        result = null;
        try {
            // 转换成增广矩阵并进行初等行变化
            double[][] mathMatrix = CalculationEquations.mathDeterminantCalculation(CalculationEquations.transferMatrix(
                    test, value));
            // 找出非零行的个数
            int checkMatrixRow = CalculationEquations.effectiveMatrix(mathMatrix);
            // 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况
            if (n > checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,少于未知数个数，所以该方程有无数组解");
            } else if (n < checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,多于未知数个数，所以该方程有无解");
            } else {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,等于未知数个数，所以该方程有解");
                result = CalculationEquations.calculationResult(mathMatrix);
                for (int i = 0; i < result.length; i++) {
                    System.out.println("方程组的解为x" + (i + 1) + "="
                            + df.format(result[i]));
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (result[0] > 0 && result[1] > 0 && result[2] < 0) {
            point[0] = result[0];
            point[1] = result[1];
            point[2] = result[2];
            return point;
        }

        return point;
    }

    /**
     * 计算C点
     *
     * @param aerfa
     * @param belta
     * @param d3
     * @param l2
     * @param x2
     * @param y2
     * @param z2
     * @return
     */
    public static double[] calPointC(double aerfa, double belta, double d3, double l2, double x2, double y2, double z2) {
        double[] point = new double[3];
        double fenmu = Math.sqrt(Math.pow(Math.sin(aerfa) * Math.cos(belta), 2) + Math.pow(Math.cos(aerfa) * Math.sin(belta), 2) + Math.pow(Math.cos(aerfa) * Math.cos(belta), 2));

        int n = 3;
        // 系数矩阵
        double[][] test = {{Math.sin(aerfa) * Math.cos(belta) / fenmu, Math.cos(aerfa) * Math.sin(belta) / fenmu, (-1) * Math.cos(aerfa) * Math.cos(belta) / fenmu},
                {0, Math.cos(belta), Math.sin(belta)},
                {z2, 0, -x2}};
        // 方程的解
        double[] value = {d3, l2, (-1) * x2 * l2 * Math.sin(belta)};
        double[] result = null;
        try {
            // 转换成增广矩阵并进行初等行变化
            double[][] mathMatrix = CalculationEquations.mathDeterminantCalculation(CalculationEquations.transferMatrix(
                    test, value));
            // 找出非零行的个数
            int checkMatrixRow = CalculationEquations.effectiveMatrix(mathMatrix);
            // 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况
            if (n > checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,少于未知数个数，所以该方程有无数组解");
            } else if (n < checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,多于未知数个数，所以该方程有无解");
            } else {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,等于未知数个数，所以该方程有解");
                result = CalculationEquations.calculationResult(mathMatrix);
                for (int i = 0; i < result.length; i++) {
                    System.out.println("方程组的解为x" + (i + 1) + "="
                            + df.format(result[i]));
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (result[0] > 0 && result[1] > 0 && result[2] < 0) {
            point[0] = result[0];
            point[1] = result[1];
            point[2] = result[2];
            return point;
        }

        test = new double[][]{{Math.sin(aerfa) * Math.cos(belta) / fenmu, Math.cos(aerfa) * Math.sin(belta) / fenmu, (-1) * Math.cos(aerfa) * Math.cos(belta) / fenmu},
                {0, Math.cos(belta), Math.sin(belta)},
                {z2, 0, -x2}};
        // 方程的解
        value = new double[]{d3, l2, (-1) * x2 * l2 * Math.sin(belta)};
        result = null;
        try {
            // 转换成增广矩阵并进行初等行变化
            double[][] mathMatrix = CalculationEquations.mathDeterminantCalculation(CalculationEquations.transferMatrix(
                    test, value));
            // 找出非零行的个数
            int checkMatrixRow = CalculationEquations.effectiveMatrix(mathMatrix);
            // 根据未知数的个数和方程组非零行的个数来判断当前方程组的解的情况
            if (n > checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,少于未知数个数，所以该方程有无数组解");
            } else if (n < checkMatrixRow) {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,多于未知数个数，所以该方程有无解");
            } else {
                System.out.println("未知数有" + n + "个，消元法后获取的阶梯方程组有"
                        + checkMatrixRow + "个方程,等于未知数个数，所以该方程有解");
                result = CalculationEquations.calculationResult(mathMatrix);
                for (int i = 0; i < result.length; i++) {
                    System.out.println("方程组的解为x" + (i + 1) + "="
                            + df.format(result[i]));
                }
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (result[0] > 0 && result[1] > 0 && result[2] < 0) {
            point[0] = result[0];
            point[1] = result[1];
            point[2] = result[2];
            return point;
        }

        return point;
    }

    /**
     * 计算Z4
     *
     * @param pointA
     * @param pointB
     * @param pointC
     * @return
     */
    public static double calZ4(double[] pointA, double[] pointB, double[] pointC) {

        double e = (pointB[1] - pointA[1]) * (pointC[2] - pointB[2]) - (pointC[1] - pointB[1]) * (pointB[2] - pointA[2]);
        double f = (pointC[0] - pointB[0]) * (pointB[2] - pointA[2]) - (pointB[0] - pointA[0]) * (pointC[2] - pointB[2]);
        double g = (pointB[0] - pointA[0]) * (pointC[1] - pointB[1]) - (pointC[0] - pointB[0]) * (pointB[1] - pointA[1]);
        double i = -e * pointB[0] - f * pointB[1] - g * pointB[2];
        double z4 = -i / g;

        return z4;
    }

    public static void calmain (String readfilepath,String writefilepath,String charSet) {
        log.info("==============> 计算主函数 <=============");
        String separator=",";
        List<String> allString = new ArrayList<>();
        List<String> allWriteString = new ArrayList<>();
        allString=FileUtils.readCsvFile(separator, readfilepath);
        for (int i =0;i<allString.size();i++) {
            log.info("==============> 第 ["+i+"]列数据 <=============");
            if (i==0) { // 列头
                String rowheader="倾角α（°）,倾角β（°）,长度L1（mm）,长度L2（mm）,测量D1（mm）,测量D2（mm）,测量D3（mm）,计算值x1（mm）,计算值y1（mm）,计算值z1（mm）,计算值x2（mm）,计算值y2（mm）,计算值z2（mm）,计算值x3（mm）,计算值y3（mm）,计算值z3（mm）,计算值z4（mm）,棱镜高度坐标Z（mm）,计算值(及画图的Y坐标）Z-/z4/（mm）,画图的x坐标（m)";

                    allWriteString.add(rowheader) ;

            } else { // 其他就开始单个计算
                String tmpStr=allString.get(i);
                String [] tmpStrList= tmpStr.split(separator);
                /**
                 *  列1:倾角α（°） 列2:倾角β（°） 列3:长度L1（mm） 列4:长度L2（mm） 列5:测量D1（mm）
                 *  列6:测量D2（mm） 列7:测量D3（mm） 列8:计算值x1（mm） 列9计算值y1（mm） 列10:计算值z1（mm）
                 *  列11:计算值x2（mm） 列12:计算值y2（mm） 列13:计算值z2（mm） 列14:计算值x3（mm） 列15:计算值y3（mm）
                 *  列16:计算值z3（mm） 列17:计算值z3（mm） 列18:计算值z4（mm） 列19:棱镜高度坐标Z（mm） 列20:计算值(及画图的Y坐标）Z-/z4/（mm）
                 *  列21:画图的x坐标（m)
                 */

                double aerfa = Double.valueOf(tmpStrList[0]) ;
                double belta = Double.valueOf(tmpStrList[1]);
                double l1 = Double.valueOf(tmpStrList[2]);
                double l2 = Double.valueOf(tmpStrList[3]);
                double d1 = Double.valueOf(tmpStrList[4]);
                double d2 = Double.valueOf(tmpStrList[5]);
                double d3 = Double.valueOf(tmpStrList[6]);
                double x1 = 0;
                double y1 = 0;
                double z1 = 0;
                double x2 = 0;
                double y2 = 0;
                double z2 = 0;
                double x3 = 0;
                double y3 = 0;
                double z3 = 0;
                double z4 = 0;
                log.info("=============> 初始值打印:"+aerfa+","+belta+","+l1+","+l2+","+d1+","+d2+","+d3+","+
                        x1+","+y1+","+z1+","+x2+","+y2+","+z2+","+x3+","+y3+","+z3+","+z4+","+ ","+ ",");

                log.info("=============> 计算B点 <============");
                double [] pointB=calPointB(aerfa,belta,d2);
                x2=pointB[0];
                y2=pointB[1];
                z2=pointB[2];

                log.info("=============> 计算A点 <============");
                double [] pointA=calPointA( aerfa,  belta,  d1,  l1,  x2,  y2,  z2);
                x1=pointA[0];
                y1=pointA[1];
                z1=pointA[2];

                log.info("=============> 计算C点 <============");
                double [] pointC=calPointC( aerfa,  belta,  d3,  l2,  x2,  y2,  z2);
                x3=pointA[0];
                y3=pointA[1];
                z3=pointA[2];

                log.info("=============> 计算Z4 <============");
                z4=calZ4(pointA, pointB, pointC);
                log.info("=============> 计算值显示 <============");
                log.info("=============: 点A{" + pointA[0]+","+ pointA[1]+","+pointA[2]+"}");
                log.info("=============: 点B{" + pointB[0]+","+ pointB[1]+","+pointB[2]+"}");
                log.info("=============: 点C{" + pointC[0]+","+ pointC[1]+","+pointC[2]+"}");
                log.info("=============: Z4:"+z4);

                log.info("=============> 构造写入文件列 <============");
                StringBuffer srtBuf=new StringBuffer();
                srtBuf.append(aerfa+","+belta+","+l1+","+l2+","+d1+","+d2+","+d3+","+
                x1+","+y1+","+z1+","+x2+","+y2+","+z2+","+x3+","+y3+","+z3+","+z4+","+ ","+ ",");
                log.info(srtBuf.toString());
                allWriteString.add(srtBuf.toString());
            }
        }

        log.info("=============> 打印计算结果 <============");
        for (int index=0;index<allWriteString.size();index++) {
            log.info(allWriteString.get(index));
        }


        log.info("==============> 计算结果写入文件 <==============");
        FileUtils.writeCsvFile(separator,writefilepath,allWriteString);

        return;
    }

    public static void main(String[] args) {
        log.info("===================> 计算主类 <==================");

        calmain ("C:/Users/pc1/Desktop/1.CSV","C:/Users/pc1/Desktop/312.CSV","gb2312");


        return;
    }
}

